'use strict';

const crypto = require('crypto');
const { getConfig } = require('uni-config-center');

// 简化的 uni-id-common 实现
class UniIdCommon {
  constructor({ context } = {}) {
    this.context = context;
    this.clientInfo = context ? {
      appId: context.APPID,
      platform: context.PLATFORM,
      locale: context.LOCALE,
      clientIP: context.CLIENTIP,
      deviceId: context.DEVICEID
    } : {};

    // 获取配置
    try {
      this.config = getConfig('uni-id');
    } catch (e) {
      console.warn('uni-id config not found, using default config');
      this.config = {
        tokenExpiresIn: 7200,
        tokenExpiresThreshold: 600,
        tokenSecret: 'default-secret-key'
      };
    }
  }

  // 微信登录方法
  async loginByWeixin(params) {
    const { code, userInfo } = params;

    if (!code) {
      return {
        errCode: 'PARAM_REQUIRED',
        errMsg: '缺少参数: code'
      };
    }

    try {
      // 调用微信接口获取 openid
      const wxConfig = this.config.oauth && this.config.oauth['mp-weixin'];
      if (!wxConfig || !wxConfig.appid || !wxConfig.appsecret) {
        throw new Error('微信小程序配置不完整');
      }

      const wxRes = await uniCloud.httpclient.request(
        `https://api.weixin.qq.com/sns/jscode2session?appid=${wxConfig.appid}&secret=${wxConfig.appsecret}&js_code=${code}&grant_type=authorization_code`,
        {
          method: 'GET',
          dataType: 'json'
        }
      );

      if (wxRes.data.errcode) {
        throw new Error(`微信登录失败: ${wxRes.data.errmsg}`);
      }

      const { openid, unionid } = wxRes.data;
      console.log('[DEBUG] 微信登录获取到的信息:', { openid, unionid });
      const db = uniCloud.database();
      const dbCmd = db.command;

      // 查找或创建用户 - 优先使用unionid查找，如果没有unionid则使用openid
      let userRes;
      if (unionid) {
        // 如果有unionid，优先使用unionid查找用户
        userRes = await db.collection('users').where({
          wx_unionid: unionid
        }).get();
      } else {
        // 如果没有unionid，使用openid查找
        // 需要兼容两种格式：字符串格式和对象格式
        userRes = await db.collection('users').where(dbCmd.or([
          { wx_openid: openid },           // 旧格式：字符串
          { 'wx_openid.mp': openid }       // 新格式：对象
        ])).get();
      }

      let uid, userInfo, type;

      if (userRes.data.length > 0) {
        // 用户已存在，登录
        const user = userRes.data[0];
        uid = user._id;
        userInfo = user;
        type = 'login';

        // 更新最后登录时间和用户信息
        const updateData = {
          last_login_date: Date.now(),
          last_login_ip: this.clientInfo.clientIP
        };

        // 更新 wx_openid，保持对象格式以兼容提现功能
        // 如果已经是对象格式，保留现有字段并更新 mp 字段
        // 如果是字符串格式，转换为对象格式
        if (typeof user.wx_openid === 'object' && user.wx_openid !== null) {
          // 已经是对象，保留现有字段并更新 mp
          updateData.wx_openid = { ...user.wx_openid, mp: openid };
        } else {
          // 字符串或不存在，创建新对象
          updateData.wx_openid = { mp: openid };
        }

        // 更新unionid（如果有的话）
        if (unionid) {
          updateData.wx_unionid = unionid;
        }

        // 如果传入了用户信息，更新昵称和头像
        if (params.userInfo) {
          updateData.nickname = params.userInfo.nickName;
          updateData.avatarUrl = params.userInfo.avatarUrl;
        }

        await db.collection('users').doc(uid).update(updateData);
        console.log('[DEBUG] 已更新用户信息:', { uid, updateData });

        // 更新返回的userInfo对象
        if (params.userInfo) {
          user.nickname = params.userInfo.nickName;
          user.avatarUrl = params.userInfo.avatarUrl;
        }
        userInfo = user;
      } else {
        // 新用户，注册
        const newUser = {
          wx_openid: { mp: openid }, // 使用对象格式存储，mp 字段用于提现
          wx_unionid: unionid,
          nickname: params.userInfo ? params.userInfo.nickName : '',
          avatarUrl: params.userInfo ? params.userInfo.avatarUrl : '',
          register_date: Date.now(),
          last_login_date: Date.now(),
          last_login_ip: this.clientInfo.clientIP,
          status: 0,
          points: 0,
          level: '健康分享者',
          commission_total: 0,
          commission_pending: 0,
          commission_available: 0
        };

        const addRes = await db.collection('users').add(newUser);
        uid = addRes.id;
        userInfo = { ...newUser, _id: uid };
        type = 'register';
        console.log('[DEBUG] 已创建新用户:', { uid, newUser });
      }

      // 生成 token
      const token = this.generateToken({ uid });
      const tokenExpired = Date.now() + this.config.tokenExpiresIn * 1000;

      return {
        errCode: 0,
        uid,
        type,
        userInfo,
        token,
        tokenExpired
      };

    } catch (error) {
      console.error('微信登录失败:', error);
      return {
        errCode: 'LOGIN_FAILED',
        errMsg: error.message || '登录失败'
      };
    }
  }

  // 检查 token
  async checkToken(token) {
    if (!token) {
      return {
        errCode: 'CHECK_TOKEN_FAILED',
        errMsg: 'token不能为空'
      };
    }

    try {
      const payload = this.verifyToken(token);
      return {
        errCode: 0,
        uid: payload.uid,
        ...payload
      };
    } catch (error) {
      return {
        errCode: 'CHECK_TOKEN_FAILED',
        errMsg: error.message || 'token校验失败'
      };
    }
  }

  // 生成 token
  generateToken(payload) {
    const header = {
      alg: 'HS256',
      typ: 'JWT'
    };

    const now = Math.floor(Date.now() / 1000);
    const tokenPayload = {
      ...payload,
      iat: now,
      exp: now + this.config.tokenExpiresIn
    };

    const headerBase64 = Buffer.from(JSON.stringify(header)).toString('base64url');
    const payloadBase64 = Buffer.from(JSON.stringify(tokenPayload)).toString('base64url');

    const signature = crypto
      .createHmac('sha256', this.config.tokenSecret || 'default-secret-key')
      .update(`${headerBase64}.${payloadBase64}`)
      .digest('base64url');

    return `${headerBase64}.${payloadBase64}.${signature}`;
  }

  // 验证 token
  verifyToken(token) {
    const parts = token.split('.');
    if (parts.length !== 3) {
      throw new Error('Invalid token format');
    }

    const [headerBase64, payloadBase64, signature] = parts;

    // 验证签名
    const expectedSignature = crypto
      .createHmac('sha256', this.config.tokenSecret || 'default-secret-key')
      .update(`${headerBase64}.${payloadBase64}`)
      .digest('base64url');

    if (signature !== expectedSignature) {
      throw new Error('Invalid token signature');
    }

    // 解析 payload
    const payload = JSON.parse(Buffer.from(payloadBase64, 'base64url').toString());

    // 检查过期时间
    if (payload.exp && payload.exp < Math.floor(Date.now() / 1000)) {
      throw new Error('Token expired');
    }

    return payload;
  }
}

// 创建实例的工厂函数
function createInstance(options = {}) {
  return new UniIdCommon(options);
}

module.exports = {
  createInstance
};
